﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;

namespace Utils.WebFramework
{
    public class GolbalCache
    {
        class StoreObject
        {
            public object Obj;
            public DateTime time = DateTime.UtcNow;
        }

        class Comparer : IComparer<DictionaryEntry>
        {
            public int Compare(DictionaryEntry x, DictionaryEntry y)
            {
                StoreObject xObj = (StoreObject)x.Value;
                StoreObject yObj = (StoreObject)y.Value;

                if (xObj.time > yObj.time)
                {
                    return 1;
                }

                if (xObj.time < yObj.time)
                {
                    return -1;
                }

                return 0;
            }
        }

        private GolbalCache() { }

        public int Capacity
        {
            get { return capacity; }
            set
            {
                if (value < MIN_CAPACITY)
                {
                    value = MIN_CAPACITY;
                }

                capacity = value;
            }
        }

        public static GolbalCache GetGolbalCache()
        {
            return golbalCache;
        }

        public void UpdateObjcet(string id, object obj)
        {
            lock (storeObjects)
            {
                StoreObject storeObject = (StoreObject)storeObjects[id];
                if (storeObject == null)
                {
                    storeObject = new StoreObject();

                    int size = storeObjects.Count;
                    if (size >= capacity)
                    {
                        DictionaryEntry[] array = GetOrderArray(size);
                        storeObjects.CopyTo(array, 0);
                        Array.Sort<DictionaryEntry>(array, 0, size, new Comparer());

                        int count = size / 2;
                        while (count-- > 0)
                        {
                            storeObjects.Remove(array[count].Key);
                        }
                    }

                    storeObjects[id] = storeObject;
                }

                storeObject.Obj = obj;
            }
        }

        public object GetObject(string id)
        {
            object obj = null;

            lock (storeObjects)
            {
                StoreObject storeObject = (StoreObject)storeObjects[id];
                if (storeObject != null)
                {
                    storeObject.time = DateTime.UtcNow;
                    obj = storeObject.Obj;
                }
            }

            return obj;
        }

        internal void Reset()
        {
            lock (storeObjects)
            {
                storeObjects.Clear();
            }
        }

        internal DictionaryEntry[] GetOrderArray(int size)
        {
            if (orderArray == null || orderArray.Length < size)
            {
                orderArray = new DictionaryEntry[size];
            }

            return orderArray;
        }

        private const int MIN_CAPACITY = 32;
        private int capacity = MIN_CAPACITY;
        private Hashtable storeObjects = new Hashtable();
        private DictionaryEntry[] orderArray = null;
        private static GolbalCache golbalCache = new GolbalCache();
    }

}
